package net.gdface.bean;

import java.lang.reflect.InvocationTargetException;
import java.util.Set;

import static net.gdface.annotations.ActiveOnClassSupport.isActive;

/**
 * 参照 common-beanutils org.apache.commons.beanutils.PropertyUtilsBean 实现 Java Bean 的多级嵌套读写，
 * 扩展支持Map,类成员，JSON String(需要JSON库[fastjson or jackson]支持) ,并提供自定义 PropertyDescriptor 支持
 * @author guyadong
 * @since 2.7.0
 */
public final class BeanPropertySupport extends BaseBeanPropertySupport {
	public static final BeanPropertySupport BEAN_SUPPORT = getBeanSupport();
	private final BaseBeanPropertySupport delegate;
	private BeanPropertySupport(BaseBeanPropertySupport delegate) {
		this.delegate = delegate;
	}

	/**
	 * @since 3.2.0
	 */
	public BaseBeanPropertySupport delegate() {
		return delegate;
	}

	@Override
	public Set<String> getPropertyNames(Class<?> beanClass, int rw, boolean lenient) {
		return delegate.getPropertyNames(beanClass, rw, lenient);
	}

	@Override
	public void clearDescriptors() {
		delegate.clearDescriptors();		
	}

	@Override
    protected Object getMappedProperty(Object bean,
                                           String name, String key)
            throws IllegalAccessException, InvocationTargetException,
            NoSuchMethodException {
		return delegate.getMappedProperty(bean, name, key);
	}
	@Override
	protected Object getIndexedProperty(Object bean,
                                            String name, int index)
            throws IllegalAccessException, InvocationTargetException,
            NoSuchMethodException {
		return delegate.getIndexedProperty(bean, name, index);
	}

	@Override
    protected  Object getSearchedProperty(Object bean,
    		String name,String field,Object conditionValue)
    				throws IllegalAccessException, InvocationTargetException,
    				NoSuchMethodException {
		return delegate.getSearchedProperty(bean, name, field, conditionValue);
	}
	@Override
    protected Object getSimpleProperty(Object bean, String name)
            throws IllegalAccessException, InvocationTargetException,
            NoSuchMethodException {
		return delegate.getSimpleProperty(bean, name);
	}
	@Override
    protected void setMappedProperty(Object bean, String name,
                                         String key, Object value)
            throws IllegalAccessException, InvocationTargetException,
            NoSuchMethodException {
    	delegate.setMappedProperty(bean, name, key, value);
	}
	@Override
	protected void setIndexedProperty(Object bean, String name,
                                          int index, Object value)
            throws IllegalAccessException, InvocationTargetException,
            NoSuchMethodException {
		delegate.setIndexedProperty(bean, name, index, value);
	}
	@Override
    protected void setSimpleProperty(Object bean,
                                         String name, Object value)
            throws IllegalAccessException, InvocationTargetException,
            NoSuchMethodException {
    	delegate.setSimpleProperty(bean, name, value);
	}

	@Override
    public void copyProperties(Object dest, Object orig, boolean ignoreNull, boolean ignoreEmpty) {
    	delegate.copyProperties(dest, orig, ignoreNull, ignoreEmpty);
	}
	
	@Override
	public void copyProperties(Object dest, Object orig) {
		delegate.copyProperties(dest, orig);
	}

	@Override
	public boolean isReadable(Object bean, String name) {
		return delegate.isReadable(bean, name);
	}

	@Override
	public boolean isWriteable(Object bean, String name) {
		return delegate.isWriteable(bean, name);
	}

	@Override
    protected Object tryConstructIfNull(Object nestedBean,Object bean, String name, Class<?> expectType) 
    		throws IllegalAccessException, InvocationTargetException, NoSuchMethodException {
		return delegate.tryConstructIfNull(nestedBean, bean, name, expectType);
	}

	private static BeanPropertySupport getBeanSupport() {
		if (isActive(net.gdface.bean.jdk.BeanPropertySupportImpl.class)) {
			return new BeanPropertySupport(net.gdface.bean.jdk.BeanPropertySupportImpl.BEAN_SUPPORT);
		} else if (isActive(net.gdface.bean.openbeans.BeanPropertySupportImpl.class)) {
			return new BeanPropertySupport(net.gdface.bean.openbeans.BeanPropertySupportImpl.BEAN_SUPPORT);
		} else {
			throw new ExceptionInInitializerError("MISS openbeans,CANT NOT CREATE BeanPropertySupport instance,"
					+ "must add dependency 'me.champeau.openbeans:openbeans:1.0.2' OR 'com.googlecode:openbeans:1.0'");
		}
	}
}
